#include "LogicSort.h"

string LogicSort::sortTasksAlphabetically(Parser::PARSED_COMMAND parsedCommand, 
											vector<Task>& tasksVector, 
											Data* _data, 
											Writer* _writer) {
	
	string statusMessage;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;

	// sort UI's display
	sort(tasksVector.begin(), tasksVector.end(), sortObjAlpha);

	dataFeedback = _data->getAll(tasks);

	if( dataFeedback == Data::NOT_FOUND ) {
		throw(NOT_FOUND_ERROR_MESSAGE);
	}

	if( dataFeedback == Data::FAILURE ) {
		// consider changing to internal error code
		throw(SORT_ERROR_MESSAGE);
	}

	sort(tasks.begin(), tasks.end(), sortObjAlpha);
	_writer->write(tasks);
	_data->executeLoad(tasks);

	if( tasksVector.empty() ) {
		statusMessage = SORT_INTERNAL_SUCCESS_MESSAGE;
	} else {
		statusMessage = SORT_ALPHA_SUCCESS_MESSAGE;
	}

	return statusMessage;
}

string LogicSort::sortTasksByFlag(Parser::PARSED_COMMAND parsedCommand, 
											vector<Task>& tasksVector, 
											Data* _data, 
											Writer* _writer) {

	string statusMessage;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;

	// sort UI's display
	sortByFlag(tasksVector);
	
	dataFeedback = _data->getAll(tasks);
	
	if( dataFeedback == Data::NOT_FOUND ) {
		throw(NOT_FOUND_ERROR_MESSAGE);
	}

	if( dataFeedback == Data::FAILURE ) {
		// consider changing to internal error code
		//logErrors(SORT_FLAG_ERROR_MESSAGE, _undoState);
		throw(SORT_FLAG_ERROR_MESSAGE);
	}
	
	sortByFlag(tasks);
	_data->executeLoad(tasks);
	_writer->write(tasks);

	if( tasksVector.empty() ) {
		statusMessage = SORT_INTERNAL_SUCCESS_MESSAGE;
	} else {
		statusMessage = SORT_FLAG_SUCCESS_MESSAGE;
	}

	return statusMessage;
}

string LogicSort::sortTasksByDateTime(Parser::PARSED_COMMAND parsedCommand, 
											vector<Task>& tasksVector, 
											Data* _data, 
											Writer* _writer) {
	string statusMessage;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;

	// sort UI's display
	sort(tasksVector.begin(), tasksVector.end(), sortObjDateTime);

	// get internal data
	dataFeedback = _data->getAll(tasks);

	if( dataFeedback == Data::NOT_FOUND ) {
		throw(NOT_FOUND_ERROR_MESSAGE);
	}

	if( dataFeedback == Data::FAILURE ) {
		// consider changing to internal error code
		//logErrors(SORT_DATE_TIME_ERROR_MESSAGE, _undoState);
		throw(SORT_DATE_TIME_ERROR_MESSAGE);
	}

	sort(tasks.begin(), tasks.end(), sortObjDateTime);
	_data->executeLoad(tasks);
	_writer->write(tasks);

	if( tasksVector.empty() ) {
		statusMessage = SORT_INTERNAL_SUCCESS_MESSAGE;
	} else {
		statusMessage = SORT_DATE_TIME_SUCCESS_MESSAGE;
	}

	return statusMessage;
}

string LogicSort::sortTasksByDone(Parser::PARSED_COMMAND parsedCommand, 
											vector<Task>& tasksVector, 
											Data* _data, 
											Writer* _writer) {

	string statusMessage;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;

	// sort UI's display
	sortByDone(tasksVector);

	// get internal data
	dataFeedback = _data->getAll(tasks);

	if( dataFeedback == Data::FAILURE ) {
		//logErrors(SORT_DONE_ERROR_MESSAGE, _undoState);
	}

	sortByDone(tasks);
	_data->executeClear();
	_data->executeLoad(tasks);
	_writer->write(tasks);
	
	if( tasksVector.empty() ) {
		statusMessage = SORT_INTERNAL_SUCCESS_MESSAGE;
	} else {
		statusMessage = SORT_SUCCESS_MESSAGE;
	}

	return statusMessage;
}

void LogicSort::sortByDone(vector<Task>& tasksVector) {
	
	vector<Task> doneTasks;
	vector<Task> undoneTasks;

	// populate doneTasks with done tasks
	for( unsigned int i=0; i<tasksVector.size(); i++ ) {
		if(tasksVector[i].getDone() == true) {
			doneTasks.push_back(tasksVector[i]);
		}
	}
	// sort the done tasks alphabetically
	sort(doneTasks.begin(), doneTasks.end(), sortObjAlpha);

	// populate undoneTasks with undone tasks
	for( unsigned int j=0; j<tasksVector.size(); j++ ) {
		if( tasksVector[j].getDone() == false ) {
			undoneTasks.push_back(tasksVector[j]);
		}
	}
	// sort the undone tasks alphabetically
	sort(undoneTasks.begin(), undoneTasks.end(), sortObjAlpha);

	tasksVector.clear();

	for( unsigned int k=0; k<doneTasks.size(); k++ ) {
		tasksVector.push_back(doneTasks[k]);
	}
	
	for( unsigned int l=0; l<undoneTasks.size(); l++ ) {
		tasksVector.push_back(undoneTasks[l]);
	}
}

void LogicSort::sortByFlag(vector<Task>& tasksVector) {

	vector<Task> flaggedTasks;
	vector<Task> unFlaggedTasks;

	// populate flaggedTasks with flagged tasks
	for( unsigned int i=0; i<tasksVector.size(); i++ ) {
		if(tasksVector[i].getDone() == true) {
			flaggedTasks.push_back(tasksVector[i]);
		}
	}
	// sort the flaggedTasks alphabetically
	sort(flaggedTasks.begin(), flaggedTasks.end(), sortObjAlpha);

	// populate unFlaggedTasks with unFlaggedTasks tasks
	for( unsigned int j=0; j<tasksVector.size(); j++ ) {
		if( tasksVector[j].getDone() == false ) {
			unFlaggedTasks.push_back(tasksVector[j]);
		}
	}
	// sort the unFlaggedTasks alphabetically
	sort(unFlaggedTasks.begin(), unFlaggedTasks.end(), sortObjAlpha);

	tasksVector.clear();

	for( unsigned int k=0; k<flaggedTasks.size(); k++ ) {
		tasksVector.push_back(flaggedTasks[k]);
	}
	
	for( unsigned int l=0; l<unFlaggedTasks.size(); l++ ) {
		tasksVector.push_back(unFlaggedTasks[l]);
	}
}

bool LogicSort::sortAlpha(Task t1, Task t2) {
	return t1.getTaskName() < t2.getTaskName();
}

bool LogicSort::sortDateTime(Task t1, Task t2) {
	return t1.getStartDateTime() < t2.getStartDateTime();
}

const string LogicSort::SORT_SUCCESS_MESSAGE = "Sort Completed";
const string LogicSort::SORT_INTERNAL_SUCCESS_MESSAGE = "File Contents Sorted";
const string LogicSort::SORT_ALPHA_SUCCESS_MESSAGE = "Sort By Alphabetical Completed";
const string LogicSort::SORT_FLAG_SUCCESS_MESSAGE = "Sort By Flag Completed";
const string LogicSort::SORT_DATE_TIME_SUCCESS_MESSAGE = "Sort By Date Time Completed";

const string LogicSort::SORT_ERROR_MESSAGE = "Unable to Sort";
const string LogicSort::SORT_FLAG_ERROR_MESSAGE = "Unable to Sort Flagged";
const string LogicSort::SORT_DATE_TIME_ERROR_MESSAGE = "Unable to Sort Date Time";
const string LogicSort::SORT_DONE_ERROR_MESSAGE = "Unable to Sort Done";

const string LogicSort::NOT_FOUND_ERROR_MESSAGE = "Task Not Found";